package cn.cool.middleware.biz_exception_retry.infra.adapter.repository;

import cn.cool.middleware.biz_exception_retry.domain.adapter.repository.IBizExceptionRetryRepository;
import cn.cool.middleware.biz_exception_retry.domain.model.entity.BizExceptionRetryRecordEntity;
import cn.cool.middleware.biz_exception_retry.domain.model.entity.RetryRecordEntity;
import cn.cool.middleware.biz_exception_retry.domain.model.valobj.BizExceptionRetryModuleVO;
import cn.cool.middleware.biz_exception_retry.domain.model.valobj.BizExceptionRetryRecordVO;
import cn.cool.middleware.biz_exception_retry.infra.mysql.BizExceptionRetryModuleMapper;
import cn.cool.middleware.biz_exception_retry.infra.mysql.BizExceptionRetryRecordMapper;
import cn.cool.middleware.biz_exception_retry.infra.mysql.po.BizExceptionRetryModulePO;
import cn.cool.middleware.biz_exception_retry.infra.mysql.po.BizExceptionRetryRecordPO;
import cn.cool.middleware.biz_exception_retry.types.common.BizExceptionRetryRecordStatusVO;
import cn.hutool.core.util.ObjUtil;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

public class BizExceptionRetryRepository implements IBizExceptionRetryRepository {
    @Resource
    private BizExceptionRetryRecordMapper bizExceptionRetryRecordMapper;

    @Resource
    private BizExceptionRetryModuleMapper bizExceptionRetryModuleMapper;

    @Override
    public Integer saveExceptionRetry(BizExceptionRetryRecordEntity record) {
        BizExceptionRetryRecordPO bizExceptionRetryRecordPO = BizExceptionRetryRecordPO.builder()
                .exceptionType(record.getExceptionType())
                .exceptionMessage(record.getExceptionMessage())
                .exceptionModule(record.getExceptionModule())
                .className(record.getClassName())
                .methodSignature(record.getMethodSignature())
                .retryParam(record.getRetryParam())
                .retryBeanName(record.getRetryBeanName())
                .objectId(record.getObjectId())
                .dealNum(record.getDealNum() != null ? record.getDealNum() : 0)
                .maxNum(record.getMaxNum() != null ? record.getMaxNum() : 6)
                .dealStatus(record.getDealStatus() != null ? record.getDealStatus() : 0)
                .dealSuccessTime(record.getDealSuccessTime())
                .build();

        return bizExceptionRetryRecordMapper.insert(bizExceptionRetryRecordPO);
    }

    @Override
    public List<BizExceptionRetryRecordVO> listExceptionRetryRecords(RetryRecordEntity recordEntity) {
        Long lastExceptionId = recordEntity.getLastExceptionId();
        String exceptionModule = recordEntity.getExceptionModule();
        Integer pageSize = recordEntity.getPageSize();

        List<BizExceptionRetryRecordPO> recordPOS = bizExceptionRetryRecordMapper.listExceptionRetryRecords(lastExceptionId, exceptionModule, pageSize);
        return recordPOS.stream().map(po -> BizExceptionRetryRecordVO.builder()
                .id(po.getId())
                .exceptionType(po.getExceptionType())
                .exceptionMessage(po.getExceptionMessage())
                .exceptionModule(po.getExceptionModule())
                .className(po.getClassName())
                .methodSignature(po.getMethodSignature())
                .retryParam(po.getRetryParam())
                .retryBeanName(po.getRetryBeanName())
                .objectId(po.getObjectId())
                .dealNum(po.getDealNum())
                .maxNum(po.getMaxNum())
                .dealStatus(po.getDealStatus())
                .dealSuccessTime(po.getDealSuccessTime())
                .build()).collect(Collectors.toList());
    }

    @Override
    public int updateRecordStatus2Processing(Long bizExceptionRetryId, Integer status) {
        return bizExceptionRetryRecordMapper.updateRecordStatus2Processing(bizExceptionRetryId, status);
    }

    @Override
    public int incrBizExceptionRetryDealNumber(Long retryId) {
        return bizExceptionRetryRecordMapper.incrBizExceptionRetryDealNumber(retryId);
    }

    @Override
    public int updateBizExceptionRetryRecordStatus(Long retryId, int recordRetryStatus) {
        BizExceptionRetryRecordPO recordPO = BizExceptionRetryRecordPO.builder().build();
        recordPO.setId(retryId);
        recordPO.setDealStatus(recordRetryStatus);
        if (recordRetryStatus == BizExceptionRetryRecordStatusVO.DEAL_SUCCESS.getStatus()) {
            recordPO.setDealSuccessTime(new Date());
        }
        return bizExceptionRetryRecordMapper.updateBizExceptionRetryRecordStatus(recordPO);
    }

    @Override
    public void insertModule(String exceptionModule) {
        bizExceptionRetryModuleMapper.insert(exceptionModule);
    }

    @Override
    public BizExceptionRetryModuleVO selectByExceptionModule(String exceptionModule) {
        BizExceptionRetryModulePO retryModulePO = bizExceptionRetryModuleMapper.selectByExceptionModule(exceptionModule);
        if (ObjUtil.isNull(retryModulePO)) return null;
        return BizExceptionRetryModuleVO.builder()
                .id(retryModulePO.getId())
                .exceptionModule(retryModulePO.getExceptionModule())
                .lockStatus(retryModulePO.getLockStatus())
                .lockTime(retryModulePO.getLockTime())
                .build();
    }

    @Override
    public int lockModule(String exceptionModule, Date oldLockTime) {
        return bizExceptionRetryModuleMapper.tryLock(exceptionModule, oldLockTime);
    }

    @Override
    public void unLock(String exceptionModule) {
        bizExceptionRetryModuleMapper.unLock(exceptionModule);
    }

}
